﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.DiagramDesigner.Helpers;
using AIStudio.Wpf.DiagramDesigner.Models;
using Newtonsoft.Json;

namespace AIStudio.Wpf.DiagramDesigner
{
    public class DiagramViewModel : BindableBase, IDiagramViewModel
    {
        #region 属性
        public ObservableCollection<SelectableDesignerItemViewModelBase> Items { get; set; } = new ObservableCollection<SelectableDesignerItemViewModelBase>();
        public List<SelectableDesignerItemViewModelBase> SelectedItems
        {
            get
            {
                return Items.Where(x => x.IsSelected).ToList();
            }
        }

        public SelectableDesignerItemViewModelBase SelectedItem
        {
            get
            {
                return SelectedItems.FirstOrDefault();
            }
        }

        private SelectionService selectionService;
        public SelectionService SelectionService
        {
            get
            {
                if (selectionService == null)
                    selectionService = new SelectionService(this);

                return selectionService;
            }
        }

        private bool _isReadOnly;
        public bool IsReadOnly
        {
            get
            {
                return _isReadOnly;
            }
            set
            {
                SetProperty(ref _isReadOnly, value);
            }
        }

        public bool IsLoading
        {
            get; set;
        }

        public IDrawModeViewModel DrawModeViewModel
        {
            get; set;
        }

        public IColorViewModel ColorViewModel
        {
            get; set;
        }

        public IFontViewModel FontViewModel
        {
            get; set;
        }

        public IShapeViewModel ShapeViewModel
        {
            get; set;
        }

        private PageSizeType _pageSizeType = PageSizeType.A4;
        public PageSizeType PageSizeType
        {
            get
            {
                return _pageSizeType;
            }
            set
            {
                SetProperty(ref _pageSizeType, value);
                RaisePropertyChanged(nameof(PageSize));
            }
        }

        private Size _pageSize = new Size(1000, 600);
        public Size PageSize
        {
            get
            {
                if (PageSizeOrientation == PageSizeOrientation.Vertical)
                {
                    return GetPageSize();
                }
                else
                {
                    return new Size(GetPageSize().Height, GetPageSize().Width);
                }
            }
            set
            {
                if (SetProperty(ref _pageSize, value))
                {
                    RaisePropertyChanged(nameof(PhysicalPageSize));
                }
            }
        }

        public Size PhysicalPageSize
        {
            get
            {
                return new Size(ScreenHelper.WidthToMm(PageSize.Width), ScreenHelper.WidthToMm(PageSize.Height));
            }
            set
            {
                PageSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height));
            }
        }

        public Size GetPageSize()
        {
            Size size = _pageSize;
            switch (PageSizeType)
            {
                case PageSizeType.A3: size = new Size(297, 420); break;
                case PageSizeType.A4: size = new Size(210, 297); break;
                case PageSizeType.A5: size = new Size(148, 210); break;
                case PageSizeType.B4: size = new Size(257, 364); break;
                case PageSizeType.B5: size = new Size(176, 250); break;
                case PageSizeType.DLEnvelope: size = new Size(110, 220); break;
                case PageSizeType.C5Envelope: size = new Size(162, 229); break;
                case PageSizeType.Quarto: size = new Size(215, 275); break;
                case PageSizeType.C6Quarto: size = new Size(114, 162); break;
                case PageSizeType.B5Quarto: size = new Size(176, 250); break;
                case PageSizeType.ItalyQuarto: size = new Size(110, 230); break;
                case PageSizeType.A4small: size = new Size(210, 297); break;
                case PageSizeType.GermanStdFanfold: size = new Size(215.9, 304.8); break;
                case PageSizeType.GermanLegalFanfold: size = new Size(203.2, 330.2); break;
                case PageSizeType.PRC16K: size = new Size(146, 215); break;
                case PageSizeType.PRC32K: size = new Size(97, 151); break;
                case PageSizeType.Letter: size = new Size(215.9, 279.4); break;
                case PageSizeType.Folio: size = new Size(215.9, 330.2); break;
                case PageSizeType.Legal: size = new Size(215.9, 355.6); break;
                case PageSizeType.Executive: size = new Size(184.15, 266.7); break;
                case PageSizeType.Statement: size = new Size(139.7, 215.9); break;
                case PageSizeType.Envelope: size = new Size(104.77, 241.3); break;
                case PageSizeType.MonarchEnvelope: size = new Size(98.425, 190.5); break;
                case PageSizeType.Tabloid: size = new Size(279.4, 431.8); break;
                case PageSizeType.LetterSmall: size = new Size(215.9, 279.4); break;
                case PageSizeType.CSheet: size = new Size(431.8, 558.8); break;
                case PageSizeType.DSheet: size = new Size(558.8, 863.6); break;
                case PageSizeType.ESheet: size = new Size(863.6, 1117.6); break;
            }

            return new Size(ScreenHelper.MmToWidth(size.Width), ScreenHelper.MmToWidth(size.Height));
        }

        private PageSizeOrientation _pageSizeOrientation;
        public PageSizeOrientation PageSizeOrientation
        {
            get
            {
                return _pageSizeOrientation;
            }
            set
            {
                SetProperty(ref _pageSizeOrientation, value);
                RaisePropertyChanged(nameof(PageSize));
            }
        }

        private PageUnit _pageUnit = PageUnit.cm;
        [Browsable(false)]
        public PageUnit PageUnit
        {
            get
            {
                return _pageUnit;
            }
            set
            {
                if (value != PageUnit.cm && value != PageUnit.inch)
                {
                    return;
                }
                SetProperty(ref _pageUnit, value);
            }
        }

        private Size _gridCellSize = new Size(100, 100);
        public Size GridCellSize
        {
            get
            {
                return _gridCellSize;
            }
            set
            {
                SetProperty(ref _gridCellSize, value);
            }
        }

        public double GridCellWidth
        {
            get
            {
                return _gridCellSize.Width;
            }
            set
            {
                _gridCellSize.Width = value;
                RaisePropertyChanged(nameof(PhysicalGridCellWidth));
                RaisePropertyChanged(nameof(GridCellSize));
            }
        }

        public double GridCellHeight
        {
            get
            {
                return _gridCellSize.Height;
            }
            set
            {
                _gridCellSize.Height = value;
                RaisePropertyChanged(nameof(PhysicalGridCellHeight));
                RaisePropertyChanged(nameof(GridCellSize));
            }
        }

        public Size PhysicalGridCellSize
        {
            get
            {
                return new Size(ScreenHelper.WidthToMm(GridCellSize.Width), ScreenHelper.WidthToMm(GridCellSize.Height));
            }
            set
            {
                GridCellSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height));
            }
        }

        public double PhysicalGridCellWidth
        {
            get
            {
                return ScreenHelper.WidthToMm(GridCellWidth);
            }
            set
            {
                GridCellWidth = ScreenHelper.MmToWidth(value);
            }
        }

        public double PhysicalGridCellHeight
        {
            get
            {
                return ScreenHelper.WidthToMm(GridCellHeight);
            }
            set
            {
                GridCellHeight = ScreenHelper.MmToWidth(value);
            }
        }

        private Color _pageBackground = Colors.White;
        public Color PageBackground
        {
            get
            {
                return _pageBackground;
            }
            set
            {
                SetProperty(ref _pageBackground, value);
            }
        }

        private bool _showGrid = true;
        public bool ShowGrid
        {
            get
            {
                return _showGrid;
            }
            set
            {
                SetProperty(ref _showGrid, value);
            }
        }

        private Color _gridColor = Colors.LightGray;
        public Color GridColor
        {
            get
            {
                return _gridColor;
            }
            set
            {
                SetProperty(ref _gridColor, value);
            }
        }

        private Size _gridMarginSize = new Size(28, 28);
        public Size GridMarginSize
        {
            get
            {
                return _gridMarginSize;
            }
            set
            {
                SetProperty(ref _gridMarginSize, value);
            }
        }

        public double GridMarginWidth
        {
            get
            {
                return _gridMarginSize.Width;
            }
            set
            {
                _gridMarginSize.Width = value;
                RaisePropertyChanged(nameof(GridMarginSize));
            }
        }

        public double GridMarginHeight
        {
            get
            {
                return _gridMarginSize.Height;
            }
            set
            {
                _gridMarginSize.Height = value;
                RaisePropertyChanged(nameof(GridMarginSize));
            }
        }

        public Size PhysicalGridMarginSize
        {
            get
            {
                return new Size(ScreenHelper.WidthToMm(GridMarginSize.Width), ScreenHelper.WidthToMm(GridMarginSize.Height));
            }
            set
            {
                GridMarginSize = new Size(ScreenHelper.MmToWidth(value.Width), ScreenHelper.MmToWidth(value.Height));
            }
        }

        public double PhysicalGridMarginWidth
        {
            get
            {
                return ScreenHelper.WidthToMm(GridMarginWidth);
            }
            set
            {
                GridMarginWidth = ScreenHelper.MmToWidth(value);
            }
        }

        public double PhysicalGridMarginHeight
        {
            get
            {
                return ScreenHelper.WidthToMm(GridMarginHeight);
            }
            set
            {
                GridMarginHeight = ScreenHelper.MmToWidth(value);
            }
        }

        private double _zoomValue = 1;
        [Browsable(false)]
        public double ZoomValue
        {
            get
            {
                return _zoomValue;
            }
            set
            {
                SetProperty(ref _zoomValue, value);
            }
        }

        private double _maximumZoomValue = 100;
        [Browsable(false)]
        public double MaximumZoomValue
        {
            get
            {
                return _maximumZoomValue;
            }
            set
            {
                SetProperty(ref _maximumZoomValue, value);
            }
        }

        private double _minimumZoomValue = 0.01;
        [Browsable(false)]
        public double MinimumZoomValue
        {
            get
            {
                return _minimumZoomValue;
            }
            set
            {
                SetProperty(ref _minimumZoomValue, value);
            }
        }

        private bool _defaultZoomBox;
        public bool DefaultZoomBox
        {
            get
            {
                return _defaultZoomBox;
            }
            set
            {
                SetProperty(ref _defaultZoomBox, value);
            }
        }

        private double _delayZoomValue = 1;
        [Browsable(false)]
        public double DelayZoomValue
        {
            get
            {
                return _delayZoomValue;
            }
            set
            {
                SetProperty(ref _delayZoomValue, value);
            }
        }

        private FitViewModel _fitViewModel;
        public FitViewModel FitViewModel
        {
            get
            {
                return _fitViewModel;
            }
            set
            {
                SetProperty(ref _fitViewModel, value);
            }
        }

        private string _name;
        [Browsable(false)]
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                SetProperty(ref _name, value);
            }
        }

        private DiagramType _diagramType;
        [Browsable(false)]
        public DiagramType DiagramType
        {
            get
            {
                return _diagramType;
            }
            set
            {
                SetProperty(ref _diagramType, value);
            }
        }

        private CellHorizontalAlignment _cellHorizontalAlignment;
        [Browsable(false)]
        public CellHorizontalAlignment CellHorizontalAlignment
        {
            get
            {
                return _cellHorizontalAlignment;
            }
            set
            {
                SetProperty(ref _cellHorizontalAlignment, value);
            }
        }

        private CellVerticalAlignment _cellVerticalAlignment;
        [Browsable(false)]
        public CellVerticalAlignment CellVerticalAlignment
        {
            get
            {
                return _cellVerticalAlignment;
            }
            set
            {
                SetProperty(ref _cellVerticalAlignment, value);
            }
        }

        private bool _isEditName;
        [Browsable(false)]
        public bool IsEditName
        {
            get
            {
                return _isEditName;
            }
            set
            {
                SetProperty(ref _isEditName, value);
            }
        }

        private System.Windows.Point _currentPoint;
        [Browsable(false)]
        public System.Windows.Point CurrentPoint
        {
            get
            {
                return _currentPoint;
            }
            set
            {
                SetProperty(ref _currentPoint, value);
            }
        }

        private Color _currentColor;
        [Browsable(false)]
        public Color CurrentColor
        {
            get
            {
                return _currentColor;
            }
            set
            {
                SetProperty(ref _currentColor, value);
            }
        }

        private string _searchText;
        public string SearchText
        {
            get
            {
                return _searchText;
            }
            set
            {
                SetProperty(ref _searchText, value);
            }
        }

        private string _searchInfo;
        public string SearchInfo
        {
            get
            {
                return _searchInfo;
            }
            set
            {
                SetProperty(ref _searchInfo, value);
            }
        }

        protected ObservableCollection<CinchMenuItem> menuOptions;
        public IEnumerable<CinchMenuItem> MenuOptions
        {
            get
            {
                return menuOptions;
            }
        }

        public bool ShowMenuOptions
        {
            get
            {
                if (MenuOptions == null || MenuOptions.Count() == 0)
                    return false;
                else
                    return true;
            }
        }

        public DiagramOption DiagramOption
        {
            get; set;
        } = new DiagramOption();

        public bool AllowDrop
        {
            get; set;
        } = true;

        public DoCommandManager DoCommandManager { get; private set; } = new DoCommandManager();

        public event DiagramEventHandler Event;

        protected double OffsetX = 10;
        protected double OffsetY = 10;
        #endregion

        #region 命令
        private ICommand _createNewDiagramCommand;
        public ICommand CreateNewDiagramCommand
        {
            get
            {
                return this._createNewDiagramCommand ?? (this._createNewDiagramCommand = new SimpleCommand(ExecuteEnable, ExecuteCreateNewDiagramCommand));
            }
        }

        private ICommand _addItemCommand;
        public ICommand AddItemCommand
        {
            get
            {
                return this._addItemCommand ?? (this._addItemCommand = new SimpleCommand(ExecuteEnable, ExecuteAddItemCommand));
            }
        }

        private ICommand _removeItemCommand;
        public ICommand RemoveItemCommand
        {
            get
            {
                return this._removeItemCommand ?? (this._removeItemCommand = new SimpleCommand(ExecuteEnable, ExecuteRemoveItemCommand));
            }
        }

        private ICommand _clearSelectedItemsCommand;
        public ICommand ClearSelectedItemsCommand
        {
            get
            {
                return this._clearSelectedItemsCommand ?? (this._clearSelectedItemsCommand = new SimpleCommand(ExecuteEnable, ExecuteClearSelectedItemsCommand));
            }
        }

        private ICommand _alignTopCommand;
        public ICommand AlignTopCommand
        {
            get
            {
                return this._alignTopCommand ?? (this._alignTopCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignTopCommand));
            }
        }

        private ICommand _alignVerticalCentersCommand;
        public ICommand AlignVerticalCentersCommand
        {
            get
            {
                return this._alignVerticalCentersCommand ?? (this._alignVerticalCentersCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignVerticalCentersCommand));
            }
        }

        private ICommand _alignBottomCommand;
        public ICommand AlignBottomCommand
        {
            get
            {
                return this._alignBottomCommand ?? (this._alignBottomCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignBottomCommand));
            }
        }

        private ICommand _alignLeftCommand;
        public ICommand AlignLeftCommand
        {
            get
            {
                return this._alignLeftCommand ?? (this._alignLeftCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignLeftCommand));
            }
        }

        private ICommand _alignHorizontalCentersCommand;
        public ICommand AlignHorizontalCentersCommand
        {
            get
            {
                return this._alignHorizontalCentersCommand ?? (this._alignHorizontalCentersCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignHorizontalCentersCommand));
            }
        }

        private ICommand _alignRightCommand;
        public ICommand AlignRightCommand
        {
            get
            {
                return this._alignRightCommand ?? (this._alignRightCommand = new SimpleCommand(ExecuteEnable, ExecuteAlignRightCommand));
            }
        }

        private ICommand _bringForwardCommand;
        public ICommand BringForwardCommand
        {
            get
            {
                return this._bringForwardCommand ?? (this._bringForwardCommand = new SimpleCommand(ExecuteEnable, ExecuteBringForwardCommand));
            }
        }

        private ICommand _bringToFrontCommand;
        public ICommand BringToFrontCommand
        {
            get
            {
                return this._bringToFrontCommand ?? (this._bringToFrontCommand = new SimpleCommand(ExecuteEnable, ExecuteBringToFrontCommand));
            }
        }

        private ICommand _sendBackwardCommand;
        public ICommand SendBackwardCommand
        {
            get
            {
                return this._sendBackwardCommand ?? (this._sendBackwardCommand = new SimpleCommand(ExecuteEnable, ExecuteSendBackwardCommand));
            }
        }

        private ICommand _sendToBackCommand;
        public ICommand SendToBackCommand
        {
            get
            {
                return this._sendToBackCommand ?? (this._sendToBackCommand = new SimpleCommand(ExecuteEnable, ExecuteSendToBackCommand));
            }
        }

        private ICommand _distributeHorizontalCommand;
        public ICommand DistributeHorizontalCommand
        {
            get
            {
                return this._distributeHorizontalCommand ?? (this._distributeHorizontalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeHorizontalCommand));
            }
        }

        private ICommand _distributeVerticalCommand;
        public ICommand DistributeVerticalCommand
        {
            get
            {
                return this._distributeVerticalCommand ?? (this._distributeVerticalCommand = new SimpleCommand(ExecuteEnable, ExecuteDistributeVerticalCommand));
            }
        }

        private ICommand _selectAllCommand;
        public ICommand SelectAllCommand
        {
            get
            {
                return this._selectAllCommand ?? (this._selectAllCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectAllCommand));
            }
        }

        private ICommand _selectInverseCommand;
        public ICommand SelectInverseCommand
        {
            get
            {
                return this._selectInverseCommand ?? (this._selectInverseCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectInverseCommand));
            }
        }

        private ICommand _selectItemCommand;
        public ICommand SelectItemCommand
        {
            get
            {
                return this._selectItemCommand ?? (this._selectItemCommand = new SimpleCommand(ExecuteEnable, ExecuteSelectItemCommand));
            }
        }

        private ICommand _copyCommand;
        public ICommand CopyCommand
        {
            get
            {
                return this._copyCommand ?? (this._copyCommand = new SimpleCommand(ExecuteEnable, ExecuteCopyCommand));
            }
        }

        private ICommand _pasteCommand;
        public ICommand PasteCommand
        {
            get
            {
                return this._pasteCommand ?? (this._pasteCommand = new SimpleCommand(ExecuteEnable, ExecutePasteCommand));
            }
        }

        private ICommand _cutCommand;
        public ICommand CutCommand
        {
            get
            {
                return this._cutCommand ?? (this._cutCommand = new SimpleCommand(ExecuteEnable, ExecuteCutCommand));
            }
        }

        private ICommand _deleteCommand;
        public virtual ICommand DeleteCommand
        {
            get
            {
                return this._deleteCommand ?? (this._deleteCommand = new SimpleCommand(ExecuteEnable, ExecuteDeleteCommand));
            }
        }

        private ICommand _leftMoveCommand;
        public ICommand LeftMoveCommand
        {
            get
            {
                return this._leftMoveCommand ?? (this._leftMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteLeftMoveCommand));
            }
        }

        private ICommand _rightMoveCommand;
        public ICommand RightMoveCommand
        {
            get
            {
                return this._rightMoveCommand ?? (this._rightMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteRightMoveCommand));
            }
        }

        private ICommand _upMoveCommand;
        public ICommand UpMoveCommand
        {
            get
            {
                return this._upMoveCommand ?? (this._upMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteUpMoveCommand));
            }
        }

        private ICommand _downMoveCommand;
        public ICommand DownMoveCommand
        {
            get
            {
                return this._downMoveCommand ?? (this._downMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteDownMoveCommand));
            }
        }

        private ICommand _centerMoveCommand;
        public ICommand CenterMoveCommand
        {
            get
            {
                return this._centerMoveCommand ?? (this._centerMoveCommand = new SimpleCommand(ExecuteEnable, ExecuteCenterMoveCommand));
            }
        }

        private ICommand _sameSizeCommand;
        public ICommand SameSizeCommand
        {
            get
            {
                return this._sameSizeCommand ?? (this._sameSizeCommand = new SimpleCommand(ExecuteEnable, ExecuteSameSizeCommand));
            }
        }

        private ICommand _sameWidthCommand;
        public ICommand SameWidthCommand
        {
            get
            {
                return this._sameWidthCommand ?? (this._sameWidthCommand = new SimpleCommand(ExecuteEnable, ExecuteSameWidthCommand));
            }
        }

        private ICommand _sameHeightCommand;
        public ICommand SameHeightCommand
        {
            get
            {
                return this._sameHeightCommand ?? (this._sameHeightCommand = new SimpleCommand(ExecuteEnable, ExecuteSameHeightCommand));
            }
        }

        private ICommand _sameAngleCommand;
        public ICommand SameAngleCommand
        {
            get
            {
                return this._sameAngleCommand ?? (this._sameAngleCommand = new SimpleCommand(ExecuteEnable, ExecuteSameAngleCommand));
            }
        }

        private ICommand _fitAutoCommand;
        public ICommand FitAutoCommand
        {
            get
            {
                return this._fitAutoCommand ?? (this._fitAutoCommand = new SimpleCommand(ExecuteEnable, ExecuteFitAutoCommand));
            }
        }

        private ICommand _fitWidthCommand;
        public ICommand FitWidthCommand
        {
            get
            {
                return this._fitWidthCommand ?? (this._fitWidthCommand = new SimpleCommand(ExecuteEnable, ExecuteFitWidthCommand));
            }
        }

        private ICommand _fitHeightCommand;
        public ICommand FitHeightCommand
        {
            get
            {
                return this._fitHeightCommand ?? (this._fitHeightCommand = new SimpleCommand(ExecuteEnable, ExecuteFitHeightCommand));
            }
        }

        private ICommand _groupCommand;
        public ICommand GroupCommand
        {
            get
            {
                return this._groupCommand ?? (this._groupCommand = new SimpleCommand(ExecuteEnable, ExecuteGroupCommand));
            }
        }

        private ICommand _ungroupCommand;
        public ICommand UngroupCommand
        {
            get
            {
                return this._ungroupCommand ?? (this._ungroupCommand = new SimpleCommand(ExecuteEnable, ExecuteUngroupCommand));
            }
        }

        private ICommand _lockCommand;
        public ICommand LockCommand
        {
            get
            {
                return this._lockCommand ?? (this._lockCommand = new SimpleCommand(ExecuteEnable, ExecuteLockCommand));
            }
        }

        private ICommand _unlockCommand;
        public ICommand UnlockCommand
        {
            get
            {
                return this._unlockCommand ?? (this._unlockCommand = new SimpleCommand(ExecuteEnable, ExecuteUnlockCommand));
            }
        }

        private ICommand _editCommand;
        public ICommand EditCommand
        {
            get
            {
                return this._editCommand ?? (this._editCommand = new SimpleCommand(ExecuteEnable, ExecuteEditCommand));
            }
        }

        private ICommand _undoCommand;
        public ICommand UndoCommand
        {
            get
            {
                return this._undoCommand ?? (this._undoCommand = new SimpleCommand(Undo_Enabled, this.ExecutedUndoCommand));
            }
        }

        private ICommand _redoCommand;
        public ICommand RedoCommand
        {
            get
            {
                return this._redoCommand ?? (this._redoCommand = new SimpleCommand(Redo_Enabled, this.ExecutedRedoCommand));
            }
        }

        private ICommand _resetLayoutCommand;
        public ICommand ResetLayoutCommand
        {
            get
            {
                return this._resetLayoutCommand ?? (this._resetLayoutCommand = new SimpleCommand(ExecuteEnable, this.ExecutedResetLayoutCommand));
            }
        }

        private ICommand _searchDownCommand;
        public ICommand SearchDownCommand
        {
            get
            {
                return this._searchDownCommand ?? (this._searchDownCommand = new SimpleCommand(ExecuteEnable, this.ExecutedSearchDownCommand));
            }
        }

        private ICommand _searchUpCommand;
        public ICommand SearchUpCommand
        {
            get
            {
                return this._searchUpCommand ?? (this._searchUpCommand = new SimpleCommand(ExecuteEnable, this.ExecutedSearchUpCommand));
            }
        }
        #endregion

        #region ctor和初始化
        public DiagramViewModel()
        {
            Mediator.Instance.Register(this);
            Items.CollectionChanged += Items_CollectionChanged;
            var zoomValueChangedSubscription = WhenPropertyChanged.Where(o => o.ToString() == nameof(ZoomValue)).Throttle(TimeSpan.FromMilliseconds(100)).Subscribe(OnZoomValueChanged);//Sample
           
            BuildMenuOptions();
        }
        public DiagramViewModel(DiagramItem diagramItem) : this()
        {
            DiagramType = diagramItem.DiagramType;
            ShowGrid = diagramItem.ShowGrid;
            PhysicalGridCellSize = diagramItem.PhysicalGridCellSize;
            CellHorizontalAlignment = diagramItem.CellHorizontalAlignment;
            CellVerticalAlignment = diagramItem.CellVerticalAlignment;
            PageSizeOrientation = diagramItem.PageSizeOrientation;
            PhysicalPageSize = diagramItem.PhysicalPageSize;
            PageSizeType = diagramItem.PageSizeType;
            PhysicalGridMarginSize = diagramItem.PhysicalGridMarginSize;
            GridColor = diagramItem.GridColor;
            AllowDrop = diagramItem.AllowDrop;

            Init(true);
        }

        public virtual void Init(bool initNew)
        {
            DoCommandManager.Init();
        }

        protected virtual void ExecutedResetLayoutCommand(object obj)
        {

        }
        #endregion

        #region 命令使能
        public virtual bool ExecuteEnable(object para)
        {
            return IsReadOnly == false;
        }
        #endregion

        #region 菜单
        private void BuildMenuOptions()
        {
            menuOptions = new ObservableCollection<CinchMenuItem>();
            CinchMenuItem menuItem = new CinchMenuItem();
            menuItem.Text = "居中";
            menuItem.Command = CenterMoveCommand;
            menuItem.CommandParameter = this;
            menuOptions.Add(menuItem);
        }
        #endregion

        #region UnDo ReDo

        private void Do(object sender, string propertyName, object newvalue)
        {
            sender.SetPropertyValue(propertyName, newvalue);
        }

        private void UnDo(object sender, string propertyName, object oldvalue)
        {
            sender.SetPropertyValue(propertyName, oldvalue);
        }


        private void ExecutedUndoCommand(object para)
        {
            Undo(para);
        }

        private bool Undo(object para)
        {
            var first = SelectedItems.OfType<DesignerItemViewModelBase>().FirstOrDefault();
            if (first != null && first.IsEditing == true)
            {
                return false;
            }

            DoCommandManager.UnDo();

            return true;
        }

        private void ExecutedRedoCommand(object para)
        {
            Redo(para);
        }

        private bool Redo(object para)
        {
            var first = SelectedItems.OfType<DesignerItemViewModelBase>().FirstOrDefault();
            if (first != null && first.IsEditing == true)
            {
                return false;
            }
            DoCommandManager.ReDo();

            return true;
        }

        private bool Undo_Enabled(object para)
        {
            return DoCommandManager.CanUnDo;
        }
        private bool Redo_Enabled(object para)
        {
            return DoCommandManager.CanReDo;
        }

        #endregion

        #region 属性改变
        private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var item in e.OldItems.OfType<SelectableDesignerItemViewModelBase>())
                {
                    item.PropertyChanged -= Item_PropertyChanged;
                    item.Dispose();
                }
            }
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems.OfType<SelectableDesignerItemViewModelBase>())
                {
                    item.PropertyChanged += Item_PropertyChanged;
                }
            }

            RaisePropertyChanged("Items");
        }

        protected virtual void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            RaisePropertyChanged(sender, e.PropertyName);
            if (e.PropertyName == "IsSelected")
            {
                RaisePropertyChanged(nameof(SelectedItem));
            }

            var selectable = sender as SelectableViewModelBase;

            if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
            {
                var property = sender.GetType().GetProperty(e.PropertyName);
                var attr = property.GetCustomAttributes(typeof(CanDoAttribute), true);
                if (attr != null && attr.Length != 0)
                {
                    //加入ReDo
                    DoCommandManager.DoNewCommand(sender.ToString() + e.PropertyName, () => Do(sender, e.PropertyName, valuePropertyChangedEventArgs.NewValue), () => UnDo(sender, e.PropertyName, valuePropertyChangedEventArgs.OldValue), null, false);

                    Event?.Invoke(sender, new DiagramEventArgs(valuePropertyChangedEventArgs.PropertyName, valuePropertyChangedEventArgs.NewValue, valuePropertyChangedEventArgs.OldValue, selectable?.Id));
                }
            }
        }

       

        //提供给标尺计算，延迟100ms，等布局改变再计算。
        private void OnZoomValueChanged(string obj)
        {
            DelayZoomValue = ZoomValue;
        }
        #endregion

        [MediatorMessageSink("DoneDrawingMessage")]
        public void OnDoneDrawingMessage(bool dummy)
        {
            foreach (var item in Items.OfType<DesignerItemViewModelBase>())
            {
                item.ShowConnectors = false;
            }
        }

        #region 新增,删除
        protected virtual void ExecuteCreateNewDiagramCommand(object parameter)
        {
            this.Items.Clear();
        }      

        private void ExecuteAddItemCommand(object parameter)
        {
            if (parameter is SelectableDesignerItemViewModelBase ite)
            {
                if (AddVerify(ite) != true) return;

                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    ClearSelectedItems();
                    Add(ite);
                },
                () => {
                    Items.Remove(ite);
                });
            }
            else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
            {
                if (items.Select(p => AddVerify(p)).Any() != true) return;

                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    ClearSelectedItems();
                    foreach (var item in items)
                    {
                        Add(item);
                    }
                },
                () => {
                    foreach (var item in items)
                    {
                        Items.Remove(item);
                    }
                });
            }
        }

        public bool AddVerify(SelectableDesignerItemViewModelBase item)
        {
            if (item.InitData() == false)
                return false;

            return true;
        }

        //使用程序添加对象，比如Demo初始化
        public void Add(object parameter)
        {
            if (parameter is SelectableDesignerItemViewModelBase ite)
            {
                if (AddVerify(ite) != true) return;

                Add(ite, false);
            }
            else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
            {
                if (items.Select(p => AddVerify(p)).Any() != true) return;

                foreach (var item in items)
                {
                    Add(item, false);
                }
            }
        }

        private void Add(SelectableDesignerItemViewModelBase item, bool isSelected = true)
        {
            item.Root = this;
            item.ZIndex = Items.Any() ? Items.Max(p => p.ZIndex) + 1 : 0;
            if (item.Id == Guid.Empty)
            {
                item.Id = Guid.NewGuid();
            }

            var logical = item as LogicalGateItemViewModelBase;
            if (logical != null && logical.LogicalType > 0)
            {
                logical.OrderNumber = Items.OfType<LogicalGateItemViewModelBase>().Count(p => (int)p.LogicalType > 0) + 1;
            }

            var designerItemViewModelBase = item as DesignerItemViewModelBase;
            if (designerItemViewModelBase != null)
            {
                designerItemViewModelBase.SetCellAlignment();
            }
            Items.Add(item);
            item.IsSelected = isSelected;
        }  

        public void Remove(object parameter)
        {
            if (parameter is SelectableDesignerItemViewModelBase ite)
            {
                ite.IsSelected = false;
                Items.Remove(ite);
            }
            else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
            {
                foreach (var item in items)
                {
                    item.IsSelected = false;
                    Items.Remove(item);
                }
            }
        }

        private void ExecuteRemoveItemCommand(object parameter)
        {
            if (parameter is SelectableDesignerItemViewModelBase ite)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    ite.IsSelected = false;
                    Items.Remove(ite);
                },
                () => {
                    Items.Add(ite);
                });
            }
            else if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> items)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    foreach (var item in items)
                    {
                        item.IsSelected = false;
                        Items.Remove(item);
                    }

                },
                () => {
                    foreach (var item in items)
                    {
                        Items.Add(item);
                    }

                });
            }
        }

        private void ExecuteClearSelectedItemsCommand(object parameter)
        {
            IEnumerable<SelectableDesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems)
            {
                item.IsSelected = false;
            }
        }

        public void ClearSelectedItems()
        {
            foreach (var item in this.SelectedItems.ToList())
            {
                item.IsSelected = false;
            }
        }

        private void ExecuteSelectAllCommand(object parameter)
        {
            foreach (var item in Items)
            {
                item.IsSelected = true;
            }
        }

        private void ExecuteSelectInverseCommand(object parameter)
        {
            foreach (var item in SelectedItems)
            {
                item.IsSelected = false;
            }
            foreach (var item in Items.Except(SelectedItems))
            {
                item.IsSelected = true;
            }
        }

        public void ExecuteSelectItemCommand(object parameter)
        {
            if (parameter is ISelectable selectable)
            {
                foreach (var item in this.Items.ToList())
                {
                    if (object.Equals(selectable, item))
                    {
                        item.IsSelected = true;
                    }
                    else
                    {
                        item.IsSelected = false;
                    }
                }
            }
        }
        #endregion

        #region 复制,粘贴
        private void ExecuteCopyCommand(object parameter)
        {
            Copy(parameter);
        }

        private bool Copy(object parameter)
        {
            List<DesignerItemViewModelBase> selectedDesignerItems;

            List<ConnectionViewModel> selectedConnections;

            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                selectedDesignerItems = para.OfType<DesignerItemViewModelBase>().ToList();
                selectedConnections = para.OfType<ConnectionViewModel>().ToList();
            }
            else
            {
                if (SelectedItems.Count == 0)
                {
                    return false;
                }
                var first = SelectedItems.OfType<DesignerItemViewModelBase>().FirstOrDefault();
                if (first != null && first.IsEditing == true)
                {
                    return false;
                }
                selectedDesignerItems = SelectedItems.OfType<DesignerItemViewModelBase>().ToList();
                selectedConnections = SelectedItems.OfType<ConnectionViewModel>().ToList();
            }


            foreach (ConnectionViewModel connection in Items.OfType<ConnectionViewModel>())
            {
                if (!selectedConnections.Contains(connection))
                {
                    DesignerItemViewModelBase sourceItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SourceConnectorInfo.DataItem.Id);
                    DesignerItemViewModelBase sinkItem = selectedDesignerItems.FirstOrDefault(p => p.Id == connection.SinkConnectorInfoFully?.DataItem?.Id);
                    if (sourceItem != null && sinkItem != null && BelongToSameGroup(sourceItem, sinkItem))
                    {
                        selectedConnections.Add(connection);
                    }
                }
            }

            string json = new SerializableObject
            {
                DesignerItems = selectedDesignerItems.Select(p => p.ToSerializableItem(".json")).Where(p => p != null).ToList(),
                Connections = selectedConnections.Select(p => p.ToSerializableItem(".json")).Where(p => p != null).ToList(),
            }.ToJson();

            OffsetX = 0;
            OffsetY = 0;
            System.Windows.Clipboard.Clear();
            System.Windows.Clipboard.SetData(System.Windows.DataFormats.Serializable, json);

            return true;
        }

        private void ExecutePasteCommand(object parameter)
        {
            Paste(parameter);
        }

        protected virtual bool Paste(object parameter)
        {
            if (System.Windows.Clipboard.ContainsData(System.Windows.DataFormats.Serializable))
            {
                string clipboardData = System.Windows.Clipboard.GetData(System.Windows.DataFormats.Serializable) as String;

                if (string.IsNullOrEmpty(clipboardData))
                    return false;
                try
                {
                    OffsetX += 10;
                    OffsetY += 10;

                    List<SelectableDesignerItemViewModelBase> items = new List<SelectableDesignerItemViewModelBase>();
                    SerializableObject copyitem = JsonConvert.DeserializeObject<SerializableObject>(clipboardData);

                    Dictionary<Guid, Guid> mappingOldToNewIDs = new Dictionary<Guid, Guid>();

                    foreach (var diagramItemData in copyitem.DesignerItems)
                    {
                        DesignerItemViewModelBase newItem = null;

                        Type type = TypeHelper.GetType(diagramItemData.ModelTypeName);

                        DesignerItemViewModelBase itemBase = Activator.CreateInstance(type, this, diagramItemData, ".json") as DesignerItemViewModelBase;
                        Guid newID = Guid.NewGuid();
                        mappingOldToNewIDs.Add(itemBase.Id, newID);
                        itemBase.Id = newID;
                        itemBase.Left += OffsetX;
                        itemBase.Top += OffsetY;

                        newItem = itemBase;

                        if (newItem != null)
                        {
                            items.Add(newItem);
                        }
                    }          

                    List<SelectableDesignerItemViewModelBase> connectors = new List<SelectableDesignerItemViewModelBase>();
                    foreach (var connection in copyitem.Connections)
                    {
                        var connectionItem = JsonConvert.DeserializeObject<ConnectionItem>(connection.SerializableString);
                        Guid newID = Guid.NewGuid();
                        mappingOldToNewIDs.Add(connectionItem.Id, newID);

                        connectionItem.SourceId = mappingOldToNewIDs[connectionItem.SourceId];
                        connectionItem.SinkId = mappingOldToNewIDs[connectionItem.SinkId];

                        connectionItem.SourceType = TypeHelper.GetType(connectionItem.SourceTypeName);
                        connectionItem.SinkType = TypeHelper.GetType(connectionItem.SinkTypeName);
                        DesignerItemViewModelBase sourceItem = DiagramViewModelHelper.GetConnectorDataItem(items, connectionItem.SourceId, connectionItem.SourceType);
                        ConnectorOrientation sourceConnectorOrientation = connectionItem.SourceOrientation;
                        FullyCreatedConnectorInfo sourceConnectorInfo = sourceItem.GetFullConnectorInfo(connectionItem.Id, sourceConnectorOrientation, connectionItem.SourceXRatio, connectionItem.SourceYRatio, connectionItem.SourceInnerPoint, connectionItem.SourceIsPortless);

                        DesignerItemViewModelBase sinkItem = DiagramViewModelHelper.GetConnectorDataItem(items, connectionItem.SinkId, connectionItem.SinkType);
                        ConnectorOrientation sinkConnectorOrientation = connectionItem.SinkOrientation;
                        FullyCreatedConnectorInfo sinkConnectorInfo = sinkItem.GetFullConnectorInfo(connectionItem.Id, sinkConnectorOrientation, connectionItem.SinkXRatio, connectionItem.SinkYRatio, connectionItem.SinkInnerPoint, connectionItem.SinkIsPortless);

                        ConnectionViewModel connectionVM = new ConnectionViewModel(this, sourceConnectorInfo, sinkConnectorInfo, connectionItem);
                        connectionVM.Id = Guid.NewGuid();
                        connectors.Add(connectionVM);
                    }

                    //修复父级的引用
                    foreach (var item in items)
                    {
                        if (item.ParentId != Guid.Empty)
                        {
                            if (mappingOldToNewIDs.ContainsKey(item.ParentId))
                                item.ParentId = mappingOldToNewIDs[item.ParentId];
                        }
                    }        
                    items.AddRange(connectors);     
                    Add(items);

                    FixOtherInfo(items);
                }
                catch (Exception e)
                {
                    System.Windows.MessageBox.Show(e.StackTrace, e.Message, System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        protected virtual void FixOtherInfo(List<SelectableDesignerItemViewModelBase> items)
        {
        
        }

        private bool ItemsToDeleteHasConnector(List<SelectableDesignerItemViewModelBase> itemsToRemove, ConnectorInfoBase connector)
        {
            if (connector is FullyCreatedConnectorInfo fully)
            {
                return itemsToRemove.Contains(fully.DataItem);
            }

            return false;
        }

        private void ExecuteCutCommand(object parameter)
        {
            Cut(parameter);
        }

        private bool Cut(object parameter)
        {
            if (Paste(null) == false)
                return false;
     
            if (Delete(null) == false)
                return false;

            return true;
        }

        protected void ExecuteDeleteCommand(object parameter)
        {
            Delete(parameter);
        }

        protected virtual bool Delete(object parameter)
        {
            List<SelectableDesignerItemViewModelBase> itemsToRemove;

            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                itemsToRemove = para.OfType<SelectableDesignerItemViewModelBase>().ToList();
            }
            else
            {
                if (SelectedItems.Count == 0)
                {
                    return false;
                }
                var first = SelectedItems.OfType<DesignerItemViewModelBase>().FirstOrDefault();
                if (first != null && first.IsEditing == true)
                {
                    return false;
                }
                itemsToRemove = SelectedItems.OfType<SelectableDesignerItemViewModelBase>().ToList();
            }

            List<SelectableDesignerItemViewModelBase> connectionsToAlsoRemove = new List<SelectableDesignerItemViewModelBase>();

            foreach (var connector in Items.OfType<ConnectionViewModel>())
            {
                if (ItemsToDeleteHasConnector(itemsToRemove, connector.SourceConnectorInfo))
                {
                    connectionsToAlsoRemove.Add(connector);
                }

                if (ItemsToDeleteHasConnector(itemsToRemove, connector.SinkConnectorInfo))
                {
                    connectionsToAlsoRemove.Add(connector);
                }

            }
            itemsToRemove.AddRange(connectionsToAlsoRemove);

            RemoveItemCommand.Execute(itemsToRemove);

            return true;
        }
        #endregion

        #region 布局
        private void ExecuteAlignTopCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }
            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double top = selectedItems.OrderBy(p => p.Top).Select(p => p.Top).FirstOrDefault();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Top, nameof(item.Top), guid.ToString());
                        item.Top = top;
                    }
                },
                 () => {
                     foreach (DesignerItemViewModelBase item in selectedItems)
                     {
                         item.Top = item.GetOldValue<double>(nameof(item.Top), guid.ToString());
                     }
                 },
                 () => {
                     foreach (DesignerItemViewModelBase item in selectedItems)
                     {
                         item.ClearOldValue<double>(nameof(item.Top), guid.ToString());
                     }
                 });
            }
        }

        private void ExecuteAlignVerticalCentersCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }
            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double mid = selectedItems.Select(p => p.Top + p.ItemHeight / 2).Average();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Top, nameof(item.Top), guid.ToString());
                        item.Top = mid - item.ItemHeight / 2;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.Top = item.GetOldValue<double>(nameof(item.Top), guid.ToString());
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.ClearOldValue<double>(nameof(item.Top), guid.ToString());
                    }
                });
            }
        }

        private void ExecuteAlignBottomCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double top = selectedItems.OrderBy(p => p.Top + p.ItemHeight).Select(p => p.Top + p.ItemHeight).LastOrDefault();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Top, nameof(item.Top), guid.ToString());
                        item.Top = top - item.ItemHeight;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.Top = item.GetOldValue<double>(nameof(item.Top), guid.ToString());
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.ClearOldValue<double>(nameof(item.Top), guid.ToString());
                    }
                });
            }
        }

        private void ExecuteAlignLeftCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double left = selectedItems.OrderBy(p => p.Left).Select(p => p.Left).FirstOrDefault();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Left, nameof(item.Left), guid.ToString());
                        item.Left = left;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.Left = item.GetOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.ClearOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                });
            }
        }

        private void ExecuteAlignHorizontalCentersCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double mid = selectedItems.Select(p => p.Left + p.ItemWidth / 2).Average();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Left, nameof(item.Left), guid.ToString());
                        item.Left = mid - item.ItemWidth / 2;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.Left = item.GetOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.ClearOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                });
            }
        }

        private void ExecuteAlignRightCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double right = selectedItems.OrderBy(p => p.Left + p.ItemWidth).Select(p => p.Left + p.ItemWidth).LastOrDefault();

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.SetOldValue(item.Left, nameof(item.Left), guid.ToString());
                        item.Left = right - item.ItemWidth;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.Left = item.GetOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        item.ClearOldValue<double>(nameof(item.Left), guid.ToString());
                    }
                });
            }
        }


        private void ExecuteBringForwardCommand(object parameter)
        {
            List<SelectableDesignerItemViewModelBase> ordered;
            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                ordered = para.OrderByDescending(p => p.ZIndex).ToList();
            }
            else
            {
                ordered = SelectedItems.OrderByDescending(p => p.ZIndex).ToList();
            }

            List<SelectableDesignerItemViewModelBase> changeditems = new List<SelectableDesignerItemViewModelBase>();
            var guid = Guid.NewGuid();

            DoCommandManager.DoNewCommand(this.ToString(),
            () => {
                int count = this.Items.Count;
                for (int i = 0; i < ordered.Count; i++)
                {
                    var item = ordered[i];
                    int currentIndex = item.ZIndex;
                    int newIndex = Math.Min(count - 1 - i, currentIndex + 1);
                    if (currentIndex != newIndex)
                    {
                        item.SetOldValue<int>(item.ZIndex, nameof(item.ZIndex), guid.ToString());
                        item.ZIndex = newIndex;
                        changeditems.Add(item);

                        IEnumerable<SelectableDesignerItemViewModelBase> it = this.Items.Where(p => p.ZIndex == newIndex);

                        foreach (var elm in it)
                        {
                            if (elm != item)
                            {
                                elm.SetOldValue<int>(elm.ZIndex, nameof(elm.ZIndex), guid.ToString());
                                elm.ZIndex = currentIndex;
                                changeditems.Add(elm);
                                break;
                            }
                        }
                    }
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ZIndex = item.GetOldValue<int>(nameof(item.ZIndex), guid.ToString());
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ClearOldValue<double>(nameof(item.ZIndex), guid.ToString());
                }
            });
        }
        private void ExecuteBringToFrontCommand(object parameter)
        {
            List<SelectableDesignerItemViewModelBase> selectionSorted;
            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                selectionSorted = para.OrderByDescending(p => p.ZIndex).ToList();
            }
            else
            {
                selectionSorted = SelectedItems.OrderByDescending(p => p.ZIndex).ToList();
            }

            List<SelectableDesignerItemViewModelBase> childrenSorted = Items.OrderByDescending(p => p.ZIndex).ToList();

            List<SelectableDesignerItemViewModelBase> changeditems = new List<SelectableDesignerItemViewModelBase>();
            var guid = Guid.NewGuid();

            DoCommandManager.DoNewCommand(this.ToString(),
            () => {
                int i = childrenSorted.Count - 1;
                int j = childrenSorted.Count - selectionSorted.Count - 1;

                foreach (SelectableDesignerItemViewModelBase item in childrenSorted)
                {
                    item.SetOldValue<int>(item.ZIndex, nameof(item.ZIndex), guid.ToString());
                    if (selectionSorted.Contains(item))
                    {
                        item.ZIndex = i--;
                    }
                    else
                    {
                        item.ZIndex = j--;
                    }
                    changeditems.Add(item);
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ZIndex = item.GetOldValue<int>(nameof(item.ZIndex), guid.ToString());
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ClearOldValue<double>(nameof(item.ZIndex), guid.ToString());
                }
            });
        }
        private void ExecuteSendBackwardCommand(object parameter)
        {
            List<SelectableDesignerItemViewModelBase> ordered;
            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                ordered = para.OrderBy(p => p.ZIndex).ToList();
            }
            else
            {
                ordered = SelectedItems.OrderBy(p => p.ZIndex).ToList();
            }

            int count = this.Items.Count;

            List<SelectableDesignerItemViewModelBase> changeditems = new List<SelectableDesignerItemViewModelBase>();
            var guid = Guid.NewGuid();

            DoCommandManager.DoNewCommand(this.ToString(),
            () => {
                for (int i = 0; i < ordered.Count; i++)
                {
                    var item = ordered[i];
                    int currentIndex = item.ZIndex;
                    int newIndex = Math.Max(i, currentIndex - 1);
                    if (currentIndex != newIndex)
                    {
                        item.SetOldValue<int>(item.ZIndex, nameof(item.ZIndex), guid.ToString());
                        item.ZIndex = newIndex;
                        changeditems.Add(item);
                        IEnumerable<SelectableDesignerItemViewModelBase> it = this.Items.Where(p => p.ZIndex == newIndex);

                        foreach (var elm in it)
                        {
                            if (elm != ordered[i])
                            {
                                elm.SetOldValue<int>(elm.ZIndex, nameof(elm.ZIndex), guid.ToString());
                                elm.ZIndex = currentIndex;
                                changeditems.Add(elm);

                                break;
                            }
                        }
                    }
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ZIndex = item.GetOldValue<int>(nameof(item.ZIndex), guid.ToString());
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ClearOldValue<double>(nameof(item.ZIndex), guid.ToString());
                }
            });
        }

        private void ExecuteSendToBackCommand(object parameter)
        {
            List<SelectableDesignerItemViewModelBase> selectionSorted;
            if (parameter is IEnumerable<SelectableDesignerItemViewModelBase> para)
            {
                selectionSorted = para.OrderByDescending(p => p.ZIndex).ToList();
            }
            else
            {
                selectionSorted = SelectedItems.OrderByDescending(p => p.ZIndex).ToList();
            }

            List<SelectableDesignerItemViewModelBase> childrenSorted = Items.OrderByDescending(p => p.ZIndex).ToList();

            List<SelectableDesignerItemViewModelBase> changeditems = new List<SelectableDesignerItemViewModelBase>();
            var guid = Guid.NewGuid();

            DoCommandManager.DoNewCommand(this.ToString(),
            () => {
                int i = childrenSorted.Count - 1;
                int j = selectionSorted.Count - 1;

                foreach (SelectableDesignerItemViewModelBase item in childrenSorted)
                {
                    item.SetOldValue<int>(item.ZIndex, nameof(item.ZIndex), guid.ToString());
                    if (selectionSorted.Contains(item))
                    {
                        item.ZIndex = j--;
                    }
                    else
                    {
                        item.ZIndex = i--;
                    }
                    changeditems.Add(item);
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ZIndex = item.GetOldValue<int>(nameof(item.ZIndex), guid.ToString());
                }
            },
            () => {
                foreach (var item in changeditems)
                {
                    item.ClearOldValue<double>(nameof(item.ZIndex), guid.ToString());
                }
            });
        }

        private void ExecuteDistributeHorizontalCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para.Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Left);
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>().Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Left);
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double left = Double.MaxValue;
                    double right = Double.MinValue;
                    double sumWidth = 0;
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        left = Math.Min(left, item.Left);
                        right = Math.Max(right, item.Left + item.ItemWidth);
                        sumWidth += item.ItemWidth;
                    }

                    double distance = Math.Max(0, (right - left - sumWidth) / (selectedItems.Count() - 1));
                    double offset = selectedItems.First().Left;

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        double delta = offset - item.Left;
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.SetOldValue(di.Left, nameof(di.Left), guid.ToString());
                            di.Left += delta;
                        }
                        offset = offset + item.ItemWidth + distance;
                    }

                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.Left = di.GetOldValue<double>(nameof(di.Left), guid.ToString());
                        }
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.ClearOldValue<double>(nameof(di.Left), guid.ToString());
                        }
                    }
                });
            }
        }

        private void ExecuteDistributeVerticalCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para.Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Top);
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>().Where(p => p.ParentId == Guid.Empty).OrderBy(p => p.Top);
            }

            var guid = Guid.NewGuid();

            if (selectedItems.Count() > 1)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    double top = Double.MaxValue;
                    double bottom = Double.MinValue;
                    double sumHeight = 0;
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        top = Math.Min(top, item.Top);
                        bottom = Math.Max(bottom, item.Top + item.ItemHeight);
                        sumHeight += item.ItemHeight;
                    }

                    double distance = Math.Max(0, (bottom - top - sumHeight) / (selectedItems.Count() - 1));
                    double offset = selectedItems.First().Top;

                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        double delta = offset - item.Top;
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.SetOldValue(di.Top, nameof(di.Top), guid.ToString());
                            di.Top += +delta;
                        }
                        offset = offset + item.ItemHeight + distance;
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.Top = di.GetOldValue<double>(nameof(di.Top), guid.ToString());
                        }
                    }
                },
                () => {
                    foreach (DesignerItemViewModelBase item in selectedItems)
                    {
                        foreach (DesignerItemViewModelBase di in SelectionService.GetGroupMembers(item))
                        {
                            di.ClearOldValue<double>(nameof(di.Top), guid.ToString());
                        }
                    }
                });
            }
        }
        #endregion     

        #region 移动
        private void ExecuteLeftMoveCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems.OfType<DesignerItemViewModelBase>())
            {
                item.Left -= 0.5;
            }
        }

        private void ExecuteRightMoveCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems.OfType<DesignerItemViewModelBase>())
            {
                item.Left += 0.5;
            }
        }

        private void ExecuteUpMoveCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems.OfType<DesignerItemViewModelBase>())
            {
                item.Top -= 0.5;
            }
        }

        private void ExecuteDownMoveCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems.OfType<DesignerItemViewModelBase>())
            {
                item.Top += 0.5;
            }
        }

        protected virtual void ExecuteCenterMoveCommand(object parameter)
        {
            IEnumerable<DesignerItemViewModelBase> selectedItems;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                selectedItems = para;
            }
            else
            {
                selectedItems = this.SelectedItems.OfType<DesignerItemViewModelBase>();
            }

            foreach (var item in selectedItems.OfType<DesignerItemViewModelBase>())
            {
                item.Left = (PageSize.Width - item.ItemWidth) / 2;
                item.Top = (PageSize.Height - item.ItemHeight) / 2;
            }

            FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(selectedItems) };
        }



        public void UpdateZIndex()
        {
            List<SelectableDesignerItemViewModelBase> ordered = Items.OrderBy(p => p.ZIndex).ToList();

            for (int i = 0; i < ordered.Count; i++)
            {
                ordered[i].ZIndex = i;
            }
        }
        #endregion

        #region 大小
        private void ExecuteSameSizeCommand(object parameter)
        {
            if (parameter is DesignerItemViewModelBase designerItem)
            {
                foreach (var item in SelectedItems.OfType<DesignerItemViewModelBase>())
                {
                    item.ItemWidth = designerItem.ItemWidth;
                    item.ItemHeight = designerItem.ItemHeight;
                }
            }
        }

        private void ExecuteSameWidthCommand(object parameter)
        {
            if (parameter is DesignerItemViewModelBase designerItem)
            {
                foreach (var item in SelectedItems.OfType<DesignerItemViewModelBase>())
                {
                    item.ItemWidth = designerItem.ItemWidth;
                }
            }
        }

        private void ExecuteSameHeightCommand(object parameter)
        {
            if (parameter is DesignerItemViewModelBase designerItem)
            {
                foreach (var item in SelectedItems.OfType<DesignerItemViewModelBase>())
                {
                    item.ItemHeight = designerItem.ItemHeight;
                }
            }
        }

        private void ExecuteSameAngleCommand(object parameter)
        {
            if (parameter is DesignerItemViewModelBase designerItem)
            {
                foreach (var item in SelectedItems.OfType<DesignerItemViewModelBase>())
                {
                    item.Angle = designerItem.Angle;
                }
            }
        }

        #endregion

        #region 适应大小
        private void ExecuteFitAutoCommand(object parameter)
        {
            FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType<DesignerItemViewModelBase>()), FitMode = FitMode.FitAuto };
        }

        private void ExecuteFitWidthCommand(object parameter)
        {
            FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType<DesignerItemViewModelBase>()), FitMode = FitMode.FitWidth };
        }

        private void ExecuteFitHeightCommand(object parameter)
        {
            FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(Items.OfType<DesignerItemViewModelBase>()), FitMode = FitMode.FitHeight };
        }
        #endregion

        #region 分组
        private void ExecuteGroupCommand(object parameter)
        {
            List<DesignerItemViewModelBase> items;
            GroupDesignerItemViewModel groupItem = null;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                if (para.FirstOrDefault() is GroupDesignerItemViewModel groupDesignerItemViewModel && groupDesignerItemViewModel.Custom)
                {
                    groupDesignerItemViewModel.Custom = false;
                    groupItem = groupDesignerItemViewModel;
                    items = para.Skip(1).ToList();
                }
                else
                {
                    items = para.ToList();
                }
            }
            else
            {
                items = SelectedItems?.OfType<DesignerItemViewModelBase>().Where(p => p.ParentId == Guid.Empty).ToList();
            }

            var groups = items.OfType<DesignerItemViewModelBase>().Where(p => p.IsGroup && p.ParentId == Guid.Empty).ToList();

            //解除分组
            if (groupItem == null && groups.Count > 0)
            {
                ExecuteUngroupCommand(groups);
                return;
            }

            RectangleBase rect = DiagramViewModelHelper.GetBoundingRectangle(items);

            if (groupItem == null)
            {
                groupItem = new GroupDesignerItemViewModel();
            }

            Add(groupItem);

            foreach (DesignerItemViewModelBase item in items)
                item.ParentId = groupItem.Id;

            groupItem.Resize();

            ClearSelectedItemsCommand.Execute(null);
            //groupItem.IsSelected = true;
            SelectionService.AddToSelection(groupItem);
        }

        private void ExecuteUngroupCommand(object parameter)
        {
            List<DesignerItemViewModelBase> groups;
            if (parameter is IEnumerable<DesignerItemViewModelBase> para)
            {
                groups = para.ToList();
            }
            else
            {
                groups = SelectedItems?.OfType<DesignerItemViewModelBase>().Where(p => p.IsGroup && p.ParentId == Guid.Empty).ToList();
            }

            foreach (DesignerItemViewModelBase groupRoot in groups)
            {
                var children = SelectedItems.OfType<DesignerItemViewModelBase>().Where(p => p.ParentId == groupRoot.Id);
                foreach (DesignerItemViewModelBase child in children)
                    child.ParentId = Guid.Empty;

                RemoveItemCommand.Execute(groupRoot);
                UpdateZIndex();
            }
        }

        public bool BelongToSameGroup(IGroupable item1, IGroupable item2)
        {
            IGroupable root1 = SelectionService.GetGroupRoot(item1);
            IGroupable root2 = SelectionService.GetGroupRoot(item2);

            return (root1.Id == root2.Id);
        }
        #endregion

        #region 快捷键操作
        public bool ExecuteShortcut(KeyEventArgs e)
        {
            if (DiagramOption.ShortcutOption.SelectAll(e))
            {
                SelectAllCommand.Execute(null);
                return true;
            }
            else if (DiagramOption.ShortcutOption.Copy(e))
            {
                return Copy(null);
            }
            else if (DiagramOption.ShortcutOption.Paste(e))
            {
                return Paste(null);
            }
            else if (DiagramOption.ShortcutOption.Cut(e))
            {
                return Cut(null);
            }
            else if (DiagramOption.ShortcutOption.Undo(e))
            {
                return Undo(null);
            }
            else if (DiagramOption.ShortcutOption.Redo(e))
            {
                return Redo(null);
            }
            else if (DiagramOption.ShortcutOption.Delete(e))
            {
                return Delete(null);
            }
            else if (DiagramOption.ShortcutOption.LeftMove(e))
            {
                LeftMoveCommand.Execute(null);
                return true;
            }
            else if (DiagramOption.ShortcutOption.RightMove(e))
            {
                RightMoveCommand.Execute(null);
                return true;
            }
            else if (DiagramOption.ShortcutOption.UpMove(e))
            {
                UpMoveCommand.Execute(null);
                return true;
            }
            else if (DiagramOption.ShortcutOption.DownMove(e))
            {
                DownMoveCommand.Execute(null);
                return true;
            }
            else if (DiagramOption.ShortcutOption.Group(e))
            {
                GroupCommand.Execute(null);
                return true;
            }

            return false;
        }
        #endregion

        #region 锁定与解锁，待完善
        private void ExecuteLockCommand(object parameter)
        {

        }

        private void ExecuteUnlockCommand(object parameter)
        {

        }
        #endregion

        #region 搜索与编辑
        protected virtual void ExecuteEditCommand(object parameter)
        {
            if (parameter is SelectableDesignerItemViewModelBase designerItem)
            {
                designerItem.ShowText = true;
            }
            else
            {
                if (SelectedItem != null)
                    SelectedItem.ShowText = true;
            }

        }

        private void ExecutedSearchUpCommand(object obj)
        {           
            if (obj != null)
            {
                var selecteddesign = SelectedItem as DesignerItemViewModelBase;
                var searchitems = Items.OfType<DesignerItemViewModelBase>().Where(p => p.Text?.Contains(obj.ToString()) == true).ToList();
                if (searchitems.Count > 0)
                {
                    int selectindex = 0;
                    if (selecteddesign != null)
                    {
                        int index = searchitems.IndexOf(selecteddesign);
                        if (index == -1)
                        {
                            selectindex = 0;
                        }
                        else if (index - 1 >= 0)
                        {
                            selectindex = index - 1;
                        }
                        else
                        {
                            selectindex = searchitems.Count - 1;
                        }
                    }
                    SelectItemCommand.Execute(searchitems[selectindex]);
                    SearchInfo = $"第{selectindex + 1}条，共{searchitems.Count}条";

                    FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(SelectedItem as DesignerItemViewModelBase) };
                }
                else
                {
                    SearchInfo = "第0条，共0条";
                }
            }
            else
            {
                SearchInfo = null;
            }
        }

        private void ExecutedSearchDownCommand(object obj)
        {
            if (!string.IsNullOrEmpty(obj?.ToString()))
            {
                var selecteddesign = SelectedItem as DesignerItemViewModelBase;
                var searchitems = Items.OfType<DesignerItemViewModelBase>().Where(p => p.Text?.Contains(obj.ToString()) == true).ToList();
                if (searchitems.Count > 0)
                {
                    int selectindex = 0;
                    if (selecteddesign != null)
                    {
                        int index = searchitems.IndexOf(selecteddesign);
                        if (index == -1)
                        {
                            selectindex = 0;
                        }
                        else if (index + 1 < searchitems.Count)
                        {
                            selectindex = index + 1;
                        }
                        else
                        {
                            selectindex = 0;
                        }
                    }
                    SelectItemCommand.Execute(searchitems[selectindex]);
                    SearchInfo = $"第{selectindex + 1}条，共{searchitems.Count}条";

                    FitViewModel = new FitViewModel() { BoundingRect = DiagramViewModelHelper.GetBoundingRectangle(SelectedItem as DesignerItemViewModelBase) };
                }
                else
                {
                    SearchInfo = "第0条，共0条";
                }
            }
            else
            {
                SearchInfo = null;
            }
        }
        #endregion
    }
}
